package org.apache.dolphinscheduler.api.utils;

import lombok.extern.slf4j.Slf4j;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * Title: 日期时间处理
 * </p>
 * <p>
 * Description: 工具类
 * </p>
 * <p>
 * Copyright: Copyright (c) 2005
 * </p>
 *
 * @version 1.0
 */
@Slf4j
public class DateUtil {

    private static DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.SIMPLIFIED_CHINESE);

    private DateUtil() {
    }

    /**
     * 返回日期　格式　2008年1月4日　星期四
     *
     * @param date
     * @return
     */
    public static String formatCWDate(Date date) {
        if (date == null)
            return "";
        else {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy年M月d日 EEE", Locale.SIMPLIFIED_CHINESE);
            return bartDateFormat.format(date);
        }
    }

    /***
     * 返回日期　格式　2008年1月4日
     *
     * @return
     * @param day
     *            相隔天数
     * @return
     */
    public static String addCWDate(int day) {
        String dayStr = "";
        try {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy年M月d日 EEE", Locale.SIMPLIFIED_CHINESE);
            dayStr = bartDateFormat.format(string2Date(dateAdd("d", day, new Date())));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return dayStr;
    }

    public static String getSendSMsgDateTime() {
        String time = "";
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = new Date();
            time = simpleDateFormat.format(date);
        } catch (Exception e) {
            time = "format datetime error:" + e.getMessage();
        }
        return time;
    }

    /**
     * 格式化字符串日期"2006-3-22 13:20:55"
     *
     * @param date
     * @return
     */
    public static String formatString(String date) {
        String dateStr = "";
        if (date == null || date.equals(""))
            return "";
        SimpleDateFormat fmt1 = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat fmt2 = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date ftDate = fmt1.parse(date);
            dateStr = fmt2.format(ftDate);
        } catch (Exception e) {
        }
        return dateStr;
    }

    /***
     * 返回日期　格式　2008年1月4日
     *
     * @param date
     * @return
     */
    public static String formatCDate(Date date) {
        if (date == null)
            return "";
        else {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy年M月d日");
            return bartDateFormat.format(date);
        }
    }

    /***
     * 返回日期　格式　2008年1月4日
     *
     * @return
     * @param day
     *            相隔天数
     * @return
     */
    public static String addCDate(int day) {
        String dayStr = "";
        try {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyyMMdd");
            dayStr = bartDateFormat.format(string2Date(dateAdd("d", day, new Date())));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return dayStr;
    }

    /***
     * 返回日期　格式　2008年1月4日
     * @return
     * @param day 相隔天数
     * @return
     */
    public static String addCDate(int day, String format) {
        String dayStr = "";
        try {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat(format);
            dayStr = bartDateFormat.format(string2Date(dateAdd("d", day, new Date())));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return dayStr;
    }

    public static String getNowDate() {
        GregorianCalendar gcNow = new GregorianCalendar();
        Date dNow = gcNow.getTime();
        DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.SIMPLIFIED_CHINESE);
        return df.format(dNow);
    }

    public static String getNowDateTime() {
        GregorianCalendar gcNow = new GregorianCalendar();
        Date dNow = gcNow.getTime();
        DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.SIMPLIFIED_CHINESE);
        return df.format(dNow);
    }

    public static int getThisYear() {
        GregorianCalendar gcNow = new GregorianCalendar();
        return gcNow.get(GregorianCalendar.YEAR);
    }

    public static int getThisMonth() {
        GregorianCalendar gcNow = new GregorianCalendar();
        return gcNow.get(GregorianCalendar.MONTH) + 1;
    }

    public static int getToDayOfMonth() {
        GregorianCalendar gcNow = new GregorianCalendar();
        return gcNow.get(GregorianCalendar.DAY_OF_MONTH);
    }

    /**
     * 返当前时间字符串yyyy-mm-dd HH:mm:ss
     */
    public static String todayString() {
        return formatSDate(new Date(System.currentTimeMillis()));
    }

    public static String formatDate(Date date) {
        if (date == null)
            return "";
        else
            return df.format(date);
    }

    public static String formatSDate(Date date) {
        if (date == null)
            return "";
        else {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return bartDateFormat.format(date);
        }
    }

    public static String formatUTCDate(Date date) {
        if (date == null)
            return "";
        else {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
            return bartDateFormat.format(date);
        }
    }

    public static String getNowYYYYMMDD() {
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyyMMdd");
        return bartDateFormat.format(new Date(System.currentTimeMillis()));
    }

    public static String getNowHHMMSS() {
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("HHmmss");
        return bartDateFormat.format(new Date(System.currentTimeMillis()));
    }

    public static String getNowYMD() {
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return bartDateFormat.format(new Date(System.currentTimeMillis()));
    }

    public static String getNowHMS() {
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("HH:mm:ss");
        return bartDateFormat.format(new Date(System.currentTimeMillis()));
    }

    public static String getNowYYYYMMDDHHmmss() {
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return bartDateFormat.format(new Date(System.currentTimeMillis()));
    }

    public static Date getDate() {
        Date date = new Date();
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-M-d");
        String datestr = bartDateFormat.format(date);
        try {
            date = bartDateFormat.parse(datestr.trim());
        } catch (Exception e) {
            System.out.println("turn dateformat find error:" + e.getMessage());
        }
        return date;
    }

    public static String dateAdd(String interval, int number, Date date) {
        String strTmp = "";
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(date);

        if (interval.equals("y")) {
            int currYear = gc.get(Calendar.YEAR);
            gc.set(Calendar.YEAR, currYear + number);
        } else if (interval.equals("m")) {
            int currMonth = gc.get(Calendar.MONTH);
            gc.set(Calendar.MONTH, currMonth + number);
        } else if (interval.equals("d")) {
            int currDay = gc.get(Calendar.DATE);
            gc.set(Calendar.DATE, currDay + number);
        } else if (interval.equals("h")) {
            int currDay = gc.get(Calendar.HOUR);
            gc.set(Calendar.HOUR, currDay + number);
        }
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-M-d HH:mm:ss");
        strTmp = bartDateFormat.format(gc.getTime());
        return strTmp;
    }

    public static String dateSAdd(String interval, int number, Date date) {
        return dateSAdd(interval, number, date, "");
    }

    public static String dateSAdd(String interval, int number, Date date, String format) {
        String strTmp = "";
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(date);

        if (interval.equals("y")) {
            int currYear = gc.get(Calendar.YEAR);
            gc.set(Calendar.YEAR, currYear + number);
        } else if (interval.equals("m")) {
            int currMonth = gc.get(Calendar.MONTH);
            gc.set(Calendar.MONTH, currMonth + number);
        } else if (interval.equals("d")) {
            int currDay = gc.get(Calendar.DATE);
            gc.set(Calendar.DATE, currDay + number);
        } else if (interval.equals("h")) {
            int currHour = gc.get(Calendar.HOUR);
            gc.set(Calendar.HOUR, currHour + number);
        }

        if (format.equals("")) {
            strTmp = df.format(gc.getTime());
        } else {
            strTmp = dateToString(gc.getTime(), format);
        }

        return strTmp;
    }

    public static String dateSMinus(String interval, int number, Date date, String format) {
        String strTmp = "";
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(date);

        if (interval.equals("y")) {
            int currYear = gc.get(Calendar.YEAR);
            gc.set(Calendar.YEAR, currYear - number);
        } else if (interval.equals("m")) {
            int currMonth = gc.get(Calendar.MONTH);
            gc.set(Calendar.MONTH, currMonth - number);
        } else if (interval.equals("d")) {
            int currDay = gc.get(Calendar.DATE);
            gc.set(Calendar.DATE, currDay - number);
        } else if (interval.equals("h")) {
            int currHour = gc.get(Calendar.HOUR);
            gc.set(Calendar.HOUR, currHour - number);
        }

        if (format.equals("")) {
            strTmp = df.format(gc.getTime());
        } else {
            strTmp = dateToString(gc.getTime(), format);
        }

        return strTmp;
    }

    /**
     * 将字符串转化为日期（java.util.Date） 字符串格式要求为 yyyy-MM-dd hh:mm:ss
     **/
    public static Date string2Date(String str) throws Exception {

        int year, month, day, hour, minute, second;
        String s1 = str.substring(0, str.indexOf(" "));
        String s2 = str.substring(str.indexOf(" ") + 1);

        StringTokenizer st = new StringTokenizer(s1, "-");
        year = Integer.parseInt(st.nextToken());
        month = Integer.parseInt(st.nextToken());
        day = Integer.parseInt(st.nextToken());

        st = new StringTokenizer(s2, ":");
        hour = Integer.parseInt(st.nextToken());
        minute = Integer.parseInt(st.nextToken());
        second = Integer.parseInt(st.nextToken());

        Calendar c = Calendar.getInstance();
        c.set(year, month - 1, day, hour, minute, second);

        return c.getTime();
    }

    /**
     * 格式化字符串日期"2006-3-22 13:20:55"
     *
     * @param date
     * @return
     */
    public static Date formatDate(String date) {
        return formatDate(date, "yyyy-MM-dd");

    }

    public static Date formatDate(String date, String format) {
        Date d1 = new Date();
        if (date == null || date.equals(""))
            return new Date();
        try {
            DateFormat df = new SimpleDateFormat(format);
            d1 = df.parse(date);
        } catch (Exception ex) {

        }
        return d1;

    }

    public static String dateString(Object dateObj) {
        if (dateObj != null)
            return dateString(dateObj.toString());
        else
            return "";
    }

    /**
     * 日期比较
     *
     * @param date1 日期1
     * @param date2 日期2
     * @return
     */
    public static int compareDateString(String date1, String date2) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        int result = -1;
        if (date1 != null || !"".equals(date1)) {
            try {
                result = dateFormat.parse(date1).compareTo(dateFormat.parse(date2));
            } catch (Exception e) {
                log.error("[compareDateString]------->" + e);
            }
        }
        return result;
    }


    /**
     * 获取交易时间yyyy-MM-dd HH:mm:ss
     *
     * @param format
     * @return
     */
    public static String getTransTime(String format) {
        DateFormat formattter = new SimpleDateFormat(format);
        Date currentTime = new Date();
        return formattter.format(currentTime);
    }

    //易钱包是否在交易时间段内 startTime   endTime 时间段
    public static boolean isTradePeriod(String startTime, String endTime, String format) {
        boolean result = false;
        try {
            DateFormat dateFormat = new SimpleDateFormat(format);
            Date startDate = dateFormat.parse(startTime);
            Date endDate = dateFormat.parse(endTime);

            String currentTime = getTransTime(format);
            Date currentDate = dateFormat.parse(currentTime);

            int startFlag = currentDate.compareTo(startDate);
            int endFlag = currentDate.compareTo(endDate);
            if (startFlag >= 0 && endFlag <= 0) {
                result = true;
            }

        } catch (Exception e) {
            log.error("isTradePeriod:" + e.getMessage());
        }

        return result;
    }


    /**
     * 日期字符串转日期
     *
     * @param dateStr 日期字符串 如20121127
     * @param format  日期格式 如YYYYMMDD
     * @return
     * @throws ParseException
     */
    public static Date stringToDate(String dateStr, String format) {
        DateFormat formatter = null;
        try {
            formatter = new SimpleDateFormat(format);
            return formatter.parse(dateStr);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 日期转日期字符串
     *
     * @param date   日期
     * @param format 日期格式 如YYYYMMDD
     * @return
     */
    public static String dateToString(Date date, String format) {
        DateFormat formatter = new SimpleDateFormat(format);
        return formatter.format(date);
    }

    /**
     * 一个日期格式的字符串转成另一种日期格式的字符串
     *
     * @param srcString 日期字符串
     * @param srcFormat 源日期格式 如YYYYMMDDHHmmss
     * @param desFormat 目的日期格式 如YYYY-MM-DD HH:mm:ss
     * @return
     * @throws ParseException
     */
    public static String dateStr2dateStr(String srcString, String srcFormat, String desFormat) {
        return dateToString(stringToDate(srcString, srcFormat), desFormat);
    }

    /**
     * 添加天数
     *
     * @param day
     * @return
     */
    public static String addDate(int day) {
        String dayStr = "";
        try {
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.SIMPLIFIED_CHINESE);
            dayStr = bartDateFormat.format(string2Date(dateAdd("d", day, new Date())));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return dayStr;
    }

    /**
     * 比较天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int compareDate(String date1, String date2) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        int result = -1;
        if (date1 != null || !"".equals(date1)) {
            try {
                result = dateFormat.parse(date1).compareTo(dateFormat.parse(date2));
            } catch (Exception e) {
                log.error("[compareDateString]------->" + e);
            }
        }
        return result;
    }

    /**
     * 通过时间秒毫秒数判断两个时间的间隔
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDaysByMillisecond(Date date1, Date date2) {
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
        return days;
    }


    /**
     * 函数功能描述:UTC时间转本地时间格式
     *
     * @param utcTime          UTC时间
     * @param localTimePattern 本地时间格式(要转换的本地时间格式)
     * @return 本地时间格式的时间
     */
    public static String utc2Local(String utcTime, String localTimePattern) {
        String utcTimePattern = "yyyy-MM-dd";
        String subTime = utcTime.substring(10);// UTC时间格式以 yyyy-MM-dd
        // 开头,将utc时间的前10位截取掉,之后是含有多时区时间格式信息的数据

        // 处理当后缀为:+8:00时,转换为:+08:00 或 -8:00转换为-08:00
        if (subTime.indexOf("+") != -1) {
            subTime = changeUtcSuffix(subTime, "+");
        }
        if (subTime.indexOf("-") != -1) {
            subTime = changeUtcSuffix(subTime, "-");
        }
        utcTime = utcTime.substring(0, 10) + subTime;

        // 依据传入函数的utc时间,得到对应的utc时间格式
        // 步骤一:处理 T
        if (utcTime.indexOf("T") != -1) {
            utcTimePattern = utcTimePattern + "'T'";
        }

        // 步骤二:处理毫秒SSS
        if (utcTime.indexOf(".") != -1) {
            utcTimePattern = utcTimePattern + "HH:mm:ss.SSS";
        } else {
            utcTimePattern = utcTimePattern + "HH:mm:ss";
        }

        // 步骤三:处理时区问题
        if (subTime.indexOf("+") != -1 || subTime.indexOf("-") != -1) {
            utcTimePattern = utcTimePattern + "XXX";
        } else if (subTime.indexOf("Z") != -1) {
            utcTimePattern = utcTimePattern + "'Z'";
        }

        if ("yyyy-MM-dd HH:mm:ss".equals(utcTimePattern) || "yyyy-MM-dd HH:mm:ss.SSS".equals(utcTimePattern)) {
            return utcTime;
        }

        SimpleDateFormat utcFormater = new SimpleDateFormat(utcTimePattern);
        utcFormater.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date gpsUtcDate = null;
        try {
            gpsUtcDate = utcFormater.parse(utcTime);
        } catch (Exception e) {
            return utcTime;
        }
        SimpleDateFormat localFormater = new SimpleDateFormat(localTimePattern);
        localFormater.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        String localTime = localFormater.format(gpsUtcDate.getTime());
        return localTime;
    }

    private static String changeUtcSuffix(String subTime, String sign) {
        String timeSuffix = null;
        String[] splitTimeArrayOne = subTime.split('\\' + sign);
        String[] splitTimeArrayTwo = splitTimeArrayOne[1].split(":");
        if (splitTimeArrayTwo[0].length() < 2) {
            timeSuffix = "+" + "0" + splitTimeArrayTwo[0] + ":" + splitTimeArrayTwo[1];
            subTime = splitTimeArrayOne[0] + timeSuffix;
            return subTime;
        }
        return subTime;
    }


    public static Date localToUTC(String localTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date localDate = null;
        try {
            localDate = sdf.parse(localTime);
        } catch (ParseException e) {
            log.error("localToUTC.error", e);
        }
        long localTimeInMillis = localDate.getTime();
        /** long时间转换成Calendar */
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(localTimeInMillis);
        calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        /** 取得时间偏移量 */
        int zoneOffset = calendar.get(java.util.Calendar.ZONE_OFFSET);
        /** 取得夏令时差 */
        int dstOffset = calendar.get(java.util.Calendar.DST_OFFSET);
        /** 从本地时间里扣除这些差量，即可以取得UTC时间*/
        calendar.add(java.util.Calendar.MILLISECOND, -(zoneOffset + dstOffset));
        /** 取得的时间就是UTC标准时间 */
        Date utcDate = new Date(calendar.getTimeInMillis());
        return utcDate;
    }

    /**
     * 获取指定年指定月的开始天数和结束天数
     */
    public static Map<String, Date> getFirstDayAndLastDayOfTheSpecifiedMonth(Integer year, Integer month) {
        // 获取当前分区的日历信息
        Calendar calendar = Calendar.getInstance();
        // 设置年
        calendar.set(Calendar.YEAR, year);
        // 设置月，月份从0开始
        calendar.set(Calendar.MONTH, month - 1);
        // 设置为指定月的第一天
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        //将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        //将秒至0
        calendar.set(Calendar.SECOND,0);
        // 获取指定月第一天的时间
        Date start = calendar.getTime();
        // 设置日历天数为当前月实际天数的最大值，即指定月份的最后一天
        calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
        //将小时至23
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        //将分钟至59
        calendar.set(Calendar.MINUTE, 59);
        //将秒至59
        calendar.set(Calendar.SECOND,59);
        // 获取最后一天的时间
        Date end = calendar.getTime();
        // 设置返回信息,返回样式根据需求自行格式化
        Map<String, Date> dateMap = new HashMap<>();
        dateMap.put("start", start);
        dateMap.put("end", end);
        return dateMap;
    }

    public static void main(String[] args) {
//        System.out.println(dateSAdd("d", -1, new Date(),"yyyy-MM-dd"));
        System.out.println(dateSMinus("d", 2, new Date(), "yyyy-MM-dd HH:mm:ss"));
//        System.out.println(dateSMinus("d", 2, new Date(),"yyyy-MM-dd HH:mm:ss"));
    }

}
